package com.redsoft.epip.controller;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.Gson;
import com.redsoft.epip.entity.Member;
import com.redsoft.epip.service.MemberService;
import com.redsoft.spirit.entity.JsonResult;
import com.redsoft.spirit.service.ComCodeTableService;

import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.mp.bean.result.WxMpUser;

@RestController
public class WxOAuthController {

	private Logger logger = LoggerFactory.getLogger(getClass());

	public static final String WX_APPID = "wxd408182127aaca73";//纸牌屋的:wxd408182127aaca73    pain测试的:wx77ce248168049af4
	public static final String WX_APPSECRET = "b259f45f35dfd86ffebcd3d4cc75018e";//纸牌屋的:b259f45f35dfd86ffebcd3d4cc75018e    pain测试的:d4624c36b6795d1d99dcf0547af5443d

	@Autowired
	private MemberService memberService;

	@Autowired
	private WxMpService wxMpService;

	@Autowired
	protected WxMpInMemoryConfigStorage wxMpConfigStorage;
	
	@Autowired
	protected WxMpMessageRouter wxMpMessageRouter;
	
	@Autowired
    private WxMpMessageRouter router;
	
	@Autowired
	private ComCodeTableService codeTableService;

	//	/**
	//	 * 微信网页授权流程: 1. 用户同意授权,获取 code 2. 通过 code 换取网页授权 access_token 3. 使用获取到的
	//	 * access_token 和 openid 拉取用户信息
	//	 * 
	//	 * @param code
	//	 *            用户同意授权后,获取到的code
	//	 * @param state
	//	 *            重定向状态参数
	//	 * @return
	//	 * @throws Exception
	//	 */
	//	@GetMapping("/**/wechatLogin")
	//	public String wechatLogin(@RequestParam(name = "code", required = false) String code,
	//			@RequestParam(name = "state") String state) throws Exception {
	//
	//		// 1. 用户同意授权,获取code
	//		logger.info("收到微信重定向跳转.");
	//		logger.info("用户同意授权,获取code:{} , state:{}", code, state);
	//
	//		// 2. 通过code换取网页授权access_token
	//		if (code != null || !(code.equals(""))) {
	//
	//			String APPID = WX_APPID;
	//			String SECRET = WX_APPSECRET;
	//			String CODE = code;
	//			String WebAccessToken = "";
	//			String openId = "";
	//			String nickName, sex, openid = "";
	//			String REDIRECT_URI = "http://www.xxx.com/url";
	//			String SCOPE = "snsapi_userinfo";
	//
	//			String getCodeUrl = UserInfoUtil.getCode(APPID, REDIRECT_URI, SCOPE);
	//			logger.info("第一步:用户同意授权，获取code, get Code URL:{}", getCodeUrl);
	//
	//			// 替换字符串，获得请求access token URL
	//			String tokenUrl = UserInfoUtil.getWebAccess(APPID, SECRET, CODE);
	//			logger.info("第二步:通过code换取网页授权access_token ,get Access Token URL:{}", tokenUrl);
	//
	//			// 通过https方式请求获得web_access_token
	//			String response = HttpsUtil.httpsRequestToString(tokenUrl, "GET", null);
	//
	//			JSONObject jsonObject = JSON.parseObject(response);
	//			logger.info("请求到的Access Token:{}", jsonObject.toJSONString());
	//
	//			// {
	//			// "access_token":"ACCESS_TOKEN",
	//			// "expires_in":7200,
	//			// "refresh_token":"REFRESH_TOKEN",
	//			// "openid":"OPENID",
	//			// "scope":"SCOPE",
	//			// "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
	//			// }
	//
	//			if (null != jsonObject) {
	//				try {
	//
	//					WebAccessToken = jsonObject.getString("access_token");
	//					openId = jsonObject.getString("openid");
	//					logger.info("获取access_token成功!");
	//					logger.info("WebAccessToken:{} , openId:{}", WebAccessToken, openId);
	//
	//					AccessTokenUtil.accessToeknMap.put(openId, WebAccessToken);
	//
	//					// 3. 使用获取到的 Access_token 和 openid 拉取用户信息
	//					String userMessageUrl = UserInfoUtil.getUserMessage(WebAccessToken, openId);
	//					logger.info("第三步:获取用户信息的URL:{}", userMessageUrl);
	//
	//					// 通过https方式请求获得用户信息响应
	//					String userMessageResponse = HttpsUtil.httpsRequestToString(userMessageUrl, "GET", null);
	//
	//					JSONObject userMessageJsonObject = JSON.parseObject(userMessageResponse);
	//
	//					Member member = new Gson().fromJson(userMessageJsonObject.toJSONString(), Member.class);
	//
	//					logger.info("用户信息:{}", userMessageJsonObject.toJSONString());
	//
	//					if (member != null) {
	//						// 往数据库存，如果有，则更新一下。
	//						memberService.save(member);
	//
	//						// state传过来的参数作为分享人的openid,进行对这个人的目前砍价数据的初始化
	//						// Map map = bargainService.initBargain(state);
	//
	//						return new JsonResult(member.getOpenId()).success().toString();
	//					}
	//				} catch (JSONException e) {
	//					logger.error("获取Web Access Token失败");
	//				}
	//			}
	//		}
	//		return new JsonResult().failure().toString();
	//	}

//		@GetMapping("/**/wxShareSign")
//		public String wxShareSign(HttpServletRequest request, String url) {
//	
////			String timestamp;
////			String nonceStr;
////			String signature;
////			String infoUrl;
////	
////			Map sign = WxUtil.getSign(url);
////			// timestamp = ((String)sign.get("timestamp"));
////			// nonceStr = ((String)sign.get("nonceStr"));
////			// signature = ((String)sign.get("signature"));
////			sign.put("appId", WX_APPID);
//	
//			return new JsonResult(sign).success().toString();
//		}

	//	// @GetMapping("/**/wxRedirect")
	//	@RequestMapping(value = "/**/wxRedirect", method = { RequestMethod.GET, RequestMethod.POST })
	//	public String checkSignature(@RequestBody(required = false) String body, HttpServletRequest request,
	//			HttpServletResponse response, String signature, String timestamp, String nonce, String echostr)
	//					throws Exception {
	//		// System.out.println(body.toString());
	//		System.out.println("================================微信URL回调测试=========================是否有echostr" + echostr);
	//		if (echostr != null && !"".equals(echostr)) {
	//			System.out.println("========这是验证服务器回调用的=======");
	//			return echostr;
	//		}
	//		SAXReader saxReader = new SAXReader();
	//		Document document;
	//		try {
	//			try {
	//				document = saxReader.read(new ByteArrayInputStream(body.toString().getBytes("UTF-8")));
	//				Element rootElt = document.getRootElement();
	//				System.out.println("FromUserName===" + rootElt.elementText("FromUserName"));
	//
	//				String openId = rootElt.elementText("FromUserName");
	//				String event = rootElt.elementText("Event");// subscribe是关注
	//															// scan是扫描
	//				String eventKey = rootElt.elementText("EventKey");// qrscene_1
	//																	// 1才是参数，需要截取
	//				String createTime = rootElt.elementText("CreateTime");
	//
	//				// 如果是关注，则进行下一步处理
	//				if ("subscribe".equals(event)) {
	//					// 去请求这个用户的基本信息
	//					String userInfoStr = WxUtil.getBaseUserInfo(WxUtil.getCurrAccessToken(), openId);
	//
	//					Member user = new Gson().fromJson(userInfoStr, Member.class);
	//
	//					if (user != null) {
	//						int subscribeFrom = Integer.parseInt(eventKey.substring(8));
	//						Date subscribeTime = new Date(Long.parseLong(createTime + "000"));
	//						user.setId(openId);
	//						user.setSubscribeTime(subscribeTime);
	//						user.setSubscribeFrom(subscribeFrom);
	//						// 往数据库存，如果有，则更新一下。
	//						memberService.save(user);
	//					}
	//
	//				}
	//			} catch (UnsupportedEncodingException e) {
	//				e.printStackTrace();
	//			}
	//		} catch (DocumentException e) {
	//			e.printStackTrace();
	//		}
	//		return echostr;
	//	}

	/**
	 * 微信网页授权流程: 1. 用户同意授权,获取 code 2. 通过 code 换取网页授权 access_token 3. 使用获取到的
	 * access_token 和 openid 拉取用户信息
	 * 
	 * @param code
	 *            用户同意授权后,获取到的code
	 * @param state
	 *            重定向状态参数
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/**/wechatLogin2")
	public String wechatLogin2(@RequestParam(name = "code", required = false) String code,
			@RequestParam(name = "state") String state) throws Exception {

		// 当用户同意授权后，会回调所设置的url并把authorization code传过来，然后用这个code获得access token
		WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);

		// 验证access token
		boolean valid = wxMpService.oauth2validateAccessToken(wxMpOAuth2AccessToken);

		if (valid) {
			// 刷新access token
			wxMpOAuth2AccessToken = wxMpService.oauth2refreshAccessToken(wxMpOAuth2AccessToken.getRefreshToken());
		}

		// 获得用户基本信息
		WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);

		Member member = new Gson().fromJson(new Gson().toJson(wxMpUser), Member.class);
		// member.setId(member.getOpenId());
		member = memberService.save(member);

		return new JsonResult(member).success().toString();
	}
	
	/**
	 * 
	 * 获取微信分享的标题、描述、图标等参数
	 * <pre>
	 * 获取微信分享的标题、描述、图标等参数
	 * </pre>
	 * 
	 * @author lixiaodong
	 * @return
	 */
	@GetMapping("/**/share/detail")
	public String getWxShareDetail() {
		Map<String, Object> params = new HashMap<String, Object>();
//		String title = codeTableService.getByInnerName(WeChatConsts.SHARE_TITLE_INNER_NAME).getItemValue();
//		String desc = codeTableService.getByInnerName(WeChatConsts.SHARE_DESC_INNER_NAME).getItemValue();
//		String avatar = codeTableService.getByInnerName(WeChatConsts.SHARE_AVATAR_INNER_NAME).getItemValue();
//		
//		params.put("title", title);
//		params.put("desc", desc);
//		params.put("avatar", avatar);
		
		return new JsonResult(params).success().toString();
	}

	/**
	 * 
	 * 获取微信公众号二维码
	 * <pre>
	 * 推荐关注用到，带有用户id
	 * </pre>
	 * 
	 * @author lixiaodong
	 * @param userId
	 * @return
	 * @throws WxErrorException
	 */
	@PostMapping("/**/qrcode/{userId}/create")
	public String getQRCode(@PathVariable String userId) throws WxErrorException {
		//有效时间7天
		//int expireSeconds = 7 * 60 * 60 * 24;
		String sceneStr = userId;

		// 临时ticket
		WxMpQrCodeTicket ticket = wxMpService.getQrcodeService().qrCodeCreateLastTicket(sceneStr);
		String qrCodeUrl = wxMpService.getQrcodeService().qrCodePictureUrl(ticket.getTicket());

		return new JsonResult(qrCodeUrl).success().toString();
	}

	/**
	 * 
	 * 获取微信端回调信息进行解密处理
	 * <pre>
	 * 获取微信端回调信息进行解密处理
	 * </pre>
	 * 
	 * @author lixiaodong
	 * @param signature
	 * @param timestamp
	 * @param nonce
	 * @param echostr
	 * @return
	 */
	@GetMapping(value="/**/auth", produces = "text/plain;charset=utf-8")
    public String authGet(
            @RequestParam(name = "signature",
                    required = false) String signature,
            @RequestParam(name = "timestamp",
                    required = false) String timestamp,
            @RequestParam(name = "nonce", required = false) String nonce,
            @RequestParam(name = "echostr", required = false) String echostr) {

        this.logger.info("\n接收到来自微信服务器的认证消息：[{}, {}, {}, {}]", signature,
                timestamp, nonce, echostr);

        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }

        if (this.wxMpService.checkSignature(timestamp, nonce, signature)) {
            return echostr;
        }

        return "非法请求";
    }

	/**
     * 
     * 获取微信端回调信息进行解密处理
     * <pre>
     * 获取微信端回调信息进行解密处理
     * </pre>
     * 
     * @author lixiaodong
     * @param requestBody
     * @param signature
     * @param timestamp
     * @param nonce
     * @param encType
     * @param msgSignature
     * @return
     */
    @PostMapping(value="/**/auth", produces = "application/xml; charset=UTF-8")
    public String post(@RequestBody String requestBody,
                       @RequestParam("signature") String signature,
                       @RequestParam("timestamp") String timestamp,
                       @RequestParam("nonce") String nonce,
                       @RequestParam(name = "encrypt_type",
                               required = false) String encType,
                       @RequestParam(name = "msg_signature",
                               required = false) String msgSignature) {
        this.logger.info(
                "\n接收微信请求：[signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                signature, encType, msgSignature, timestamp, nonce, requestBody);

        if (!this.wxMpService.checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法请求，可能属于伪造的请求！");
        }

        String out = null;
        if (encType == null) {
            // 明文传输的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
            WxMpXmlOutMessage outMessage = this.route(inMessage);
            if (outMessage == null) {
                return "";
            }

            out = outMessage.toXml();
        } else if ("aes".equals(encType)) {
            // aes加密的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(
                    requestBody, this.wxMpService.getWxMpConfigStorage(), timestamp,
                    nonce, msgSignature);
            this.logger.debug("\n消息解密后内容为：\n{} ", inMessage.toString());
            WxMpXmlOutMessage outMessage = this.route(inMessage);
            if (outMessage == null) {
                return "";
            }

            out = outMessage
                    .toEncryptedXml(this.wxMpService.getWxMpConfigStorage());
        }

        this.logger.debug("\n组装回复信息：{}", out);

        return out;
    }

    /**
     * 
     * 转发路由
     * <pre>
     * 转发路由
     * </pre>
     * 
     * @author lixiaodong
     * @param message
     * @return
     */
    private WxMpXmlOutMessage route(WxMpXmlMessage message) {
        try {
            return this.router.route(message);
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
        }

        return null;
    }

}